/*
 * Copyright 2007 Brian Watkins
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package bw.os;

import javax.servlet.*;
import java.util.*;
import bw.util.*;

public abstract class AsynchronousObjectWriter extends PersistentObjectHandler
    implements PersistentObjectWriter
{
    private Worker _worker = null;

    //note this class is asynchronous in the sense that it executes write and erase
    //calls to objectStore in a thread other than the caller. It is not asynchronous
    //in the sense that there is a pool of workers doing this. In fact, we want there
    //to be only one worker so that changes are committed to the persistent store in
    //the order that they occur. 

    public AsynchronousObjectWriter ( ServletContext context )
    {
        _worker = new Worker( this.getClass().getName() );
        _worker.start();
    }

    public AsynchronousObjectWriter ()
    {
        //nothing
    }

    public void write ( String key, Object obj ) throws Exception
    {
        _worker.addWork( new ObjectWriter( key, obj ) );
    }
    
    public void erase ( String key ) throws Exception
    {
        _worker.addWork( new ObjectEraser( key ) );
    }

    public void shutdown () throws Exception
    {
        _worker.shutdown();
    }

    protected abstract void asynchronousWrite ( String key, Object obj ) throws Exception;

    protected abstract void asynchronousErase ( String key ) throws Exception;

    class ObjectEraser implements Runnable
    {
        private String _key = null;
        
        public ObjectEraser ( String key )
        {
            _key = key;
        }

        public void run ()
        {
            try
            {
                asynchronousErase( _key );
            }
            catch ( Exception ex )
            {
                Log.getInstance().write( "Problem erasing key: " + _key );
            }
        }
    }

    class ObjectWriter implements Runnable
    {
        private String _key = null;
        private Object _object = null;

        public ObjectWriter ( String key, Object obj )
        {
            _key = key;
            _object = obj;
        }

        public void run ()
        {
            try
            {
                asynchronousWrite( _key, _object );
            }
            catch ( Exception ex )
            {
                Log.getInstance().write( "Problem writing key: " + _key, ex );
            }
        }
    }
}